<template>
    <div class="rank-box">
        <div>
            <el-button class="refresh" size="default" type="primary" @click="start">刷新</el-button>
        </div>
        <!-- :max-height="`calc(100vh - 64px - var(--container-margin)* 5 - var(--container-header-height) - var(--rank-header-height )`" -->
        <el-table class="match-rank-table" :data="tableData" style="width: 100%" :max-height="`calc(100vh - 24px)`">
            <template v-slot:empty>
                <el-empty image="https://cdn-hterobot.oss-cn-qingdao.aliyuncs.com/image/ojSass-empty.png" />
            </template>
            <el-table-column type="index" label="排名" align="center" width="80" fixed></el-table-column>
            <el-table-column prop="username" label="成员" align="center" width="150" fixed show-overflow-tooltip>
                <template #default="{ row }">
                    {{ row.xingming ? `${row.xingming} (${row.name})` : row.name }}
                </template>
            </el-table-column>
            <el-table-column prop="df" label="总分" align="center" width="" sortable></el-table-column>

            <el-table-column v-for="(item, key) in matchQuestion" :key="key" align="center" :prop="String(key)"
                :label="`#${key + 1}(${item.score})`" class-name="el-table-column"
                label-class-name="match-rank-table-header" width="" sortable>
                <template #header="{ row }">
                    <el-tooltip effect="dark" :content="`${item.type}-${item.name}`" placement="top">
                        <div>
                            <div class="match-rank-table-header-qNo">
                                {{ `# ${key + 1} ` }}
                            </div>
                            <div class="match-rank-table-header-qScore">
                                {{ `${item.score} ` }}
                            </div>
                        </div>
                    </el-tooltip>
                </template>
                <template #default="{ row }">
                    <!-- 代码题-弹窗展示源码和测试点情况 只有isAdmin或者本人 才能查看代码、测试点信息 -->
                    <div v-if="item.type === '代码'">
                        <el-tooltip v-if="iswatchcode || isAdmin || row.userId === user?.ID" effect="dark"
                            :content="`点击查看详情`" placement="top">
                            <div :class="className(row, item, key)" class="cursor-pointer score-box"
                                @click="showCode(row, item, key)">
                                {{ row.rank[key].score }}
                            </div>
                        </el-tooltip>
                        <div v-else :class="className(row, item, key)" class="score-box">
                            {{ row.rank[key].score }}
                        </div>
                    </div>
                    <div v-else :class="className(row, item, key)">
                        {{ row.rank[key].score }}
                    </div>
                </template>
            </el-table-column>
        </el-table>
        <!-- 弹窗 -->
        <el-dialog v-model="dialogVisible" width="60%" :before-close="handleClose">
            <template #header>
                <span class="icon-text el-dialog__header-title">
                    <el-icon class="text-primary">
                        <Guide />
                    </el-icon>
                    得分详情
                </span>
            </template>
            <div class="padding0-20">
                <h6 class="source-detail-title"> {{ sourceDetail.userName }} - {{ sourceDetail.name }}</h6>
                <h6 class="margin-bottom0">题目总得分：{{ sourceDetail.score }}</h6>
            </div>
            <el-row class="dialog-content">
                <el-col :span="12" class="left">
                    <el-row class="test-case-title">
                        <h6 class="margin-bottom0">测试点得分</h6>
                    </el-row>
                    <el-scrollbar>
                        <div class="test-case-container" v-for="(v, infoK) in sourceDetail.testScores"
                            :key="'a_' + infoK" :class="ALLTYPE[v[3]][1]">
                            <div class="test-case-content">
                                <div class="test-case-head">
                                    <span class="test-case-num font-size14"> #{{ infoK + 1 }} </span>
                                    <span class="test-case-ac"> {{ v[3] }} </span>
                                </div>
                                <strong class="test-case-score">{{ v[0] }}</strong>
                                <span class="test-case-time font-size13">
                                    <!-- {{ v[1] }}ms /{{ v[2] }}kb -->
                                    {{ formatMetrics(v[1], v[2]) }}
                                </span>
                            </div>
                        </div>
                    </el-scrollbar>
                </el-col>
                <el-col :span="12" class="right">
                    <el-row class="source-code-title">
                        <h6 class="margin-bottom0">源代码</h6>
                        <div class="margin-left10">
                            <!-- <el-button class="submission-btn" size="default" type="primary"
                                @click="myCopy(sourceDetail.sourceCode || '')">复制源代码
                            </el-button> -->
                            <el-icon class="icon cursor-pointer" @click="myCopy(sourceDetail.sourceCode || '')">
                                <CopyDocument />
                            </el-icon>
                        </div>
                    </el-row>
                    <div class="col p-0">
                        <pre v-highlight :class="'language-' + sourceDetail.sourceLanguage">
                    <code v-text="sourceDetail.sourceCode" class="code-pre"></code>
                </pre>
                    </div>
                </el-col>
            </el-row>
            <template #footer>
                <el-button type="primary" size="default" @click="dialogVisible = false">关闭</el-button>
            </template>
        </el-dialog>
    </div>
</template>

<script setup lang="ts">
import { useClipboard } from '@vueuse/core';
import { ElMessage } from "element-plus";
import { encode } from "js-base64";
import { computed, onMounted, reactive, ref, watch } from 'vue';
import { useRouter } from "vue-router";
import { useStore } from "vuex";
import { asyncgetactivity, asyncselectmatchquestion, asyncselectmatchranking, asyncteamselectmatchuserquestion } from "../../../api";
import { Storekey } from "../../../interface";
import Studycodemodel from "../../../mysql_interface/studycodemodel";
import { ALLTYPE } from "@/util/jianchatime";
const { text, copy, copied, isSupported } = useClipboard()

type P = {
    activity: Studycodemodel.Iactivity
}
const p = defineProps<P>()
const router = useRouter();
const store = useStore(Storekey)
const user = computed(() => {
    return store.state.user
})
const teamId = computed(() => {
    return user.value?.teamid;
});
const isAdmin = computed(() => {
    return user.value?.isAdmin
})

const limit = ref(1000)
const offset = ref(0)
const activity = reactive<Studycodemodel.Iactivity>({});
const format = computed(() => {
    return p.activity.format
})

const matchQuestion = ref<Studycodemodel.Imatchquestion[]>([{ score: 0 }])
async function selectmatchquestion() {
    const [data] = await asyncselectmatchquestion({ activityid: p.activity.ID })
    matchQuestion.value = data.matchquestion || []
}

watch(() => p.activity.ID, (v) => {
    if (v) start()
})
onMounted(async () => {
    await start()

})
async function start() {
    if (!p.activity.ID) return
    const data = await asyncgetactivity({ ID: p.activity.ID });
    Object.assign(activity, data);
    if (!activity.isranking) return
    getMatchRanking()
    selectmatchquestion()
}
const users = ref<Studycodemodel.Iuser[]>([])
const matchRanking = ref<Studycodemodel.Imatchranking[]>([])
async function getMatchRanking() {
    const { user, matchranking } = await asyncselectmatchranking({
        activityid: p.activity.ID,
        _offset: offset.value, _limit: limit.value, _order: 'df', _sortable: 'DESC'
    })
    users.value = user
    matchRanking.value = matchranking
}

// 组装数据
const tableData = computed(() => {
    const matchQ = matchQuestion.value.map(e => ({ name: e.name, type: e.type }))
    const ret = users.value.map(u => {
        let rank: { type: string, score: number }[] = []
        const { ID } = u
        // 某个人的rank Info
        const matchranking = matchRanking.value.find(e => e.userid === ID) || {}
        // [[type, df, name, ac],[...]]
        const _data = JSON.parse(matchranking?.data || '') as any[]

        rank = matchQuestion.value.map((e, i) => {
            const answered = _data.find(z => z[2] === e.name)
            // const answered = _data[i]
            // 赛后成绩不需要掩饰
            let score = answered ? answered[1] || 0 : 0
            // 是否答题
            let isAnswered = !!answered
            return {
                type: e.type,
                score,
                // [20, 8, 892, "AC"]
                acList: answered ? answered[4] || [] : [],
                isAnswered
            }
        })
        // 是否全AC
        const resultdata = _data.map(e => e[3]).filter(e => e === 'AC').length === _data.length ? 'AC' : 'UN'
        return {
            rank,
            ...u,
            ...matchranking,
            resultdata
        }
    }).sort((a, b) => Number(b.df) - Number(a.df))
    return ret //.concat(ret).concat(ret).concat(ret).concat(ret).concat(ret).concat(ret).concat(ret).concat(ret).concat(ret).concat(ret).concat(ret)
})

// 
const dialogVisible = ref(false);
const sourceDetail = reactive({
    userName: "",
    name: "",
    score: "",
    testScores: [],
    sourceCode: "",
    sourceLanguage: "",
})

async function showCode(userMatchQuestion: any, item: Studycodemodel.Imatchquestion, index: number) {
    const { userid, name, score } = userMatchQuestion
    sourceDetail.userName = name || ""
    sourceDetail.name = item.name || ""
    if (item.type === '代码') {
        try {
            const { rows } = await asyncteamselectmatchuserquestion({
                userid,
                questionid: item.ID,
                activityid: p.activity.ID,
                teamid: activity.teamid || teamId.value
            })
            if (rows.length) {
                const { context, language } = rows[0]
                sourceDetail.sourceLanguage = language || "";
                sourceDetail.sourceCode = context || "";
                // 使用 selectmatchuserquestion 返回的info 重新计算subtask 内部测试点 
                sourceDetail.testScores = userMatchQuestion.rank[index]?.acList;
                sourceDetail.score = userMatchQuestion.rank[index]?.score
                dialogVisible.value = true;
            } else {
                ElMessage.error('没有找到此题答题记录')
            }
        } catch (e) {
            ElMessage.error(e as any)
        }
    } else {
        ElMessage.error('此题不是代码题')
    }
}

function handleClose(done: () => void) {
    dialogVisible.value = false;
    done();
}

async function getcode(params: any, item: Studycodemodel.Imatchquestion) {
    const { userid, name } = params
    const questionid = item.ID
    const activityid = p.activity.ID
    const teamid = activity.teamid || teamId.value
    if (item.type === '代码') {
        try {
            const { rows } = await asyncteamselectmatchuserquestion({
                userid,
                questionid,
                activityid,
                teamid
            })
            if (rows.length) {
                const { context, language } = rows[0]
                window.open(`https://cdn.hterobot.com/diffeditor/index.html?code1=${encode(String(context), true)}&language=${language}&name1=${encode(name + ' ' + item.name, true)}`)
            } else {
                ElMessage.error('没有找到此题')
            }
        } catch (e) {
            ElMessage.error(e as any)
        }
    } else {
        ElMessage.error('此题不是代码题')
    }
}
function className(params: Studycodemodel.Imatchranking, matchquestion: Studycodemodel.Imatchquestion, index: number) {
    const { data } = params
    const _data = JSON.parse(data || '[]') as any[]
    const n = _data[index] || []
    const c = (n[1] || 0) / Number(matchquestion.score)
    if (c >= 0.7) {
        return 'Accepted'
    } else if (c >= 0.3) {
        return 'Unaccepted'
    } else {
        return 'CompileError'
    }
}
function myCopy(str: string) {
    try {
        str ? copy(str) : '';
        ElMessage.success("复制成功");
    } catch (error) {
        console.error("myCopy error=>", str, error)
    }
}

function formatMetrics(time: number, size: number, toFixed: number = 1) {
    let formattedTime;
    if (time >= 1000) {
        formattedTime = (time / 1000).toFixed(toFixed) + 's';
    } else {
        formattedTime = time + 'ms';
    }
    let formattedSize;
    if (size >= 1024) {
        formattedSize = (size / 1024).toFixed(toFixed) + 'mb';
    } else {
        formattedSize = size + 'kb';
    }
    return `${formattedTime} / ${formattedSize}`;
}
</script>

<style scoped>
.rank-box {
    /* height: calc(100vh - 64px - var(--container-margin)* 5 - var(--container-header-height)); */
    margin: 0;
    height: 100%;
    /* 设置为可以滚动 */
    overflow-y: auto;
    --rank-header-height: 40px;
}

.fixed-header .el-table__header-wrapper {
    position: sticky;
    top: 0;
    /* 固定在顶部 */
    z-index: 10;
    /* 确保表头在内容之上 */
    background-color: #fff;
    /* 设置表头背景色，避免遮挡问题 */
}

.rank-header {
    display: flex;
    justify-content: space-between;
    height: var(--rank-header-height);
    align-items: center;
}

.refresh {
    border-radius: 5px;
}

.cu:hover {
    text-decoration: underline;
}

.match-rank-table-header-qNo,
.match-rank-table-header-qScore {
    position: relative;
}

.match-rank-table-header-qScore {
    color: #7f7f7f;
    font-size: 12px;
}

.tips {
    position: absolute;
    left: 0;
    /* display: inline-block; */
    /* float: left; */
}

.score-box {
    border: 1px solid;
    max-width: 90px;
    margin: auto;
    padding: 5px 0;
    opacity: .5;
    color: #fff;
}

.score-box:hover {
    opacity: 1;
}

/*  */
.dialog-content {}

.left {
    padding-left: 20px;
}

.right {
    padding-right: 20px;
}

.source-detail-title {
    margin-bottom: 12px;
}

.source-code-title,
.test-case-title {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin: 15px 0;
}

.source-code-title {
    justify-content: flex-start;
}

/* 测试点 */

.test-case-container {
    width: 108px;
    height: 104px;
    /* padding: 5px; */
    margin: 5px;
    display: inline-block;
    border-radius: 5px;
    overflow: hidden;
    box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.1);
}

.test-case-container .test-case-content {
    border-top-width: 4px;
    border-top-style: solid;
}


.test-case-content .test-case-num {
    padding-left: 8px;
    padding-right: 4px;
    color: #909399 !important;
}

.test-case-content .test-case-score {
    font-size: 36px;
    display: block;
    text-align: center;
}

.test-case-content .test-case-time {
    display: block;
    text-align: center;
    color: #909399 !important;
}
</style>

<style>
#activity-common-layout .match-rank-table-header .cell .caret-wrapper {
    /* width: 10px; */
}

#activity-common-layout .match-rank-table-header .cell {
    padding: 0;
    margin: auto;
    /* 换行 */
    white-space: pre-wrap;
    line-height: normal;
    /* 排序 */
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

#activity-common-layout .score-box.Accepted {
    background-color: var(--color-3ac2a2);
}

#activity-common-layout .score-box.Unaccepted {
    background-color: #f5ac50;
}

#activity-common-layout .score-box.CompileError {
    background-color: #ff5249;
}
</style>